#ifndef UTILS_H
#define UTILS_H
#include <syslog.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
//#define Log(fmt, ...) LogD(fmt,##__VA_ARGS__);
//#define LogD(fmt, ...) LogLevel(7,fmt,##__VA_ARGS__);
//#define LogI(fmt, ...) LogLevel(6,fmt,##__VA_ARGS__);
//#define LogE(fmt, ...) LogLevel(3,fmt,##__VA_ARGS__);
//#define LogC(fmt,...) printf(("[%s:%d] %s: " fmt "\n"), __FILE__, __LINE__, __PRETTY_FUNCTION__, ##__VA_ARGS__);
//#define LogLevel(__level__,fmt, ...) logger_syslog(__level__,("[%s:%d] %s: " fmt "\n"), __FILE__, __LINE__, __PRETTY_FUNCTION__, ##__VA_ARGS__)
#define QUOTEME(x) #x
#define QUOTEME_FUNC(__name) QUOTEME(__name)

#define Log(fmt, ...) LogD(fmt,##__VA_ARGS__);
#define LogD(fmt, ...) LogLevel(LOG_DEBUG,fmt,##__VA_ARGS__);
#define LogI(fmt, ...) LogLevel(LOG_INFO,fmt,##__VA_ARGS__);
#define LogE(fmt, ...) LogLevel(LOG_ERR,fmt,##__VA_ARGS__);
#define LogC(fmt,...) LogD(fmt,##__VA_ARGS__);
#define LogLevel(__level__,fmt, ...) sipxmpp_loglevel(__level__,("[%s:%d]: " fmt "\n"), __FILE__, __LINE__, ##__VA_ARGS__)

#define SIPXMPP_DEBUG_LEVEL_LOWEST 1
#ifndef DEFAULT_DEBUG_LEVEL
#define DEFAULT_DEBUG_LEVEL 2
#endif

int sipxmpp_loglevel(int level,char *fmt,...);

#define sipxmpp_debug(__level__,__fmt__,...) {if(__level__ >= DEFAULT_DEBUG_LEVEL) LogD(__fmt__,##__VA_ARGS__);}
#define gotofinish(err_code) retcode=err_code;goto finish;
#define xmpp_cmpstr(x1,x2,x1_len) memcmp(x1,x2,MIN(x1_len,strlen(x2)))

#define NTOHS(n) (((((unsigned short)(n) & 0xFF)) << 8) | (((unsigned short)(n) & 0xFF00) >> 8))
#define HTONS(n) NTOHS(n)
#define HTONL(n) (((((unsigned long)(n) & 0xFF)) << 24) | \
                  ((((unsigned long)(n) & 0xFF00)) << 8) | \
                  ((((unsigned long)(n) & 0xFF0000)) >> 8) | \
                  ((((unsigned long)(n) & 0xFF000000)) >> 24))

#define NTOHL(n) HTONL(n)
#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
#ifdef MEMORY_LEAK_WATCHER
	#define sipxmpp_calloc(__calloc_size__) memory_watcher_calloc(__FILE__, __LINE__,__calloc_size__)
	#define sipxmpp_realloc(_ptr_,_size_) memory_watcher_realloc(__FILE__, __LINE__,_ptr_,_size_);
	#define chkndfree(__pointer__); if(__pointer__){memory_watcher_free(__FILE__, __LINE__,__pointer__);__pointer__ = NULL;}
	void memory_watcher_init();
	void memory_watcher_destroy();
	void *memory_watcher_calloc(char *file,int line,size_t size);
	void *memory_watcher_realloc(char *file,int line,void *ptr, size_t size);
	void memory_watcher_free(char *file,int line,void *ptr);

#else
	#define sipxmpp_calloc(__calloc_size__) calloc(__calloc_size__,1)
	#define sipxmpp_realloc(_ptr_,_size_) realloc(_ptr_,_size_);
	#define chkndfree(__pointer__); if(__pointer__){free(__pointer__);__pointer__ = NULL;}
#endif

#define S_ERROR 1
#define S_OK 0


static char fourbits2char[16] =  { '0', '1', '2', '3', '4', '5',
    '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
inline static int string2hex( 
	/* input */ unsigned char *str, int len,
	/* output */ char *hex )
{
	int orig_len;

	if (len==0) {
		*hex='0';
		return 1;
	}

	orig_len=len;
	while ( len ) {

		*hex=fourbits2char[((*str) >> 4) & 0x0f];
		hex++;
		*hex=fourbits2char[(*str) & 0x0f];
		hex++;
		len--;
		str++;

	}
	return orig_len-len;
}
inline static void sipxmpp_createrandomdata(char *randsid,int randlen)
{
	int rand_fd = open("/dev/urandom", O_RDONLY); 
	int readbytes = read(rand_fd, randsid, randlen);
	if(readbytes != randlen)
	{
		Log("error reading bytes");
	}
	close(rand_fd);
}
inline static int mem_atoi(char *ptr,int len)
{
	int i=0,result = 0;
	for(i=0; i<len; i++)
	{
		result = result * 10 + ptr[i] - '0';
	}
	return result;
}
char *base64_decode(const char *buf);
char *base64_encode(const char *buf, int len);
int logger_init();

#endif
